﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.Net;
using System.IO;
using HtmlAgilityPack;
using System.Text.RegularExpressions;
using System.Threading;

namespace SiteRecord
{

    public class CrawlEngine
    {
        private string _url;
        public string URL
        {
            get
            {
                return _url;
            }
            set
            {
                OriginalUrl = value;
                _url = string.Format(Utility.SearchEngineUrl, Utility.Prefix, value);
            }
        }

        public string Title { get; set; }

        public string OriginalUrl { get; set; }

        public HtmlWeb WebClientEngine { get; set; }

        private HtmlDocument _currentdoc;
        public HtmlDocument CurrentDoc
        {
            get
            {
                if (_currentdoc==null)
                {
                    _currentdoc = LoadPage();
                }
                return _currentdoc;
            }
        }

        readonly Regex isDigital = new Regex(@"^[0-9]+$");

        public HtmlNode ContainerNode
        {
            get
            {

                HtmlNode node = CurrentDoc.GetElementbyId("container");
                while (node == null)
                {
                    node = CurrentDoc.GetElementbyId("container");
                    Thread.Sleep(200);
                }
                return node;
            }
        }

        public CrawlEngine()
        {
            WebClientEngine = new HtmlWeb { OverrideEncoding = Encoding.UTF8 };
        }

        public Records Load(string url)
        {
            this.URL = url;
            
            return Load();
        }

        public Records Load()
        {
        //    Title = LoadTitle();

            return new Records
                    {
                        RecordCount = LoadSiteRecordCount(),
                        RecordDate = LoadSiteRecordDate(),
                        ModifyDate = DateTime.Now.Date,
                        SnapshotUrl = AnalysisSnapshotUrl()
                    };


        }


        public int LoadSiteRecordCount()
        {
            string rc = ContainerNode.SelectSingleNode("//p[1]").FirstChild.InnerText;
            string count = string.Empty;
            int tempcount = 0;

            if (NoRecords(rc))
                return tempcount;

            for (int i = 0; i < rc.Length; i++)
            {
                if (isDigital.IsMatch(rc[i].ToString()))
                    count += rc[i];
            }

            int.TryParse(count, out tempcount);

            return tempcount;
        }

 

        public DateTime? LoadSiteRecordDate()
        {
            string[] datePar = AnalysisIndexInfo();
            if (datePar == null) return DateTime.Now;

            DateTime date;

            if (DateTime.TryParse(datePar[1], out date))
                return date;

            return DateTime.Now;
        }


        private string[] AnalysisIndexInfo()
        {
            HtmlNode DateNode = ContainerNode.SelectSingleNode("//p[1]");
            DateNode = DateNode != null ? DateNode.NextSibling : null;

            HtmlNode node = DateNode != null ? DateNode.SelectSingleNode("//tr[1]/td[1]/font[1]/span[1]") : null;
            if (node == null) return null;


            if (node.InnerText.EToString().Trim().IndexOf("...") != -1)
                return null;

            return node.InnerText.EToString().Trim().Split(' ');
        }

        private string AnalysisSnapshotUrl()
        {
            string[] datePar = AnalysisIndexInfo();
            if (datePar == null) return string.Empty;

            if (RemoveRub(datePar[0]) == OriginalUrl) return OriginalUrl;
            return string.Empty;

        }

        private string RemoveRub(string p)
        {
            return p.Replace("/", "").Replace("http://","");
        }
        
        public string LoadTitle()
        {
            HtmlNode TitleNode = ContainerNode != null ? ContainerNode.SelectSingleNode("//p[1]") : null;
            TitleNode = TitleNode != null ? TitleNode.NextSibling : null;
            HtmlNode node = TitleNode != null ? TitleNode.SelectSingleNode("//tr[1]/td[1]/h3[1]/a[1]") : null;

            return node != null ? node.InnerText : string.Empty;
        }


        private bool NoRecords(string rc)
        {
            return rc.IndexOf("抱歉") != -1;
        }

        private HtmlDocument LoadPage()
        {
            if (URL.IsNullOrEmpty())
            {
                throw new Exception("URL 为空！");
            }

            HtmlDocument dochtml = new HtmlDocument();
            dochtml.LoadHtml(GetPage(URL));
            while (dochtml.DocumentNode.ChildNodes.Count == 0)
            {
                dochtml.LoadHtml(GetPage(URL));
                Thread.Sleep(500);
            }
            return dochtml;




            /*/html[1]/body[1]/div[1]/div[1]/div[1]/div[3]/p[1]
             * 
            var htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(GetPage("http://www.baidu.com/s?wd=site%3Awww.9idev.com", Encoding.Default));

            HtmlNode ContainerNode = htmlDoc.GetElementbyId("container");
            ContainerNode.SelectNodes("/p");
            ContainerNode.SelectNodes("/table[0]");*/
        }

        public string GetPage(string url)
        {

            HttpWebRequest request = null;
            HttpWebResponse response = null;
            StreamReader reader = null;
            try
            {
                request = (HttpWebRequest)WebRequest.Create(url);
                request.UserAgent = "www.svnhost.cn";
                request.Timeout = 20000;
                request.AllowAutoRedirect = false;

                response = (HttpWebResponse)request.GetResponse();
                 
                while(response.StatusCode == HttpStatusCode.OK && response.ContentLength < 1024 * 512)
                {

                    reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                    string html = reader.ReadToEnd();

                    return html;
                }
            }
            catch
            {
            }

            finally
            {
                if (response != null)
                {

                    response.Close();

                    response = null;

                }
                if (reader != null)

                    reader.Close();

                if (request != null)

                    request = null;

            }

            return string.Empty;

        }



    }
}